home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / intrlib1.zip / INTR_DJG.CC < prev    next >
C/C++ Source or Header  |  1992-03-10  |  37KB  |  1,083 lines

  1. /******************************************************************************
  2. * Low level graphics routines(DJGPP driver).                      *
  3. *                                          *
  4. * This file is compiled in C++ mode.                          *
  5. *                                          *
  6. *                    Written by Gershon Elber,  Feb. 1992  *
  7. *******************************************************************************
  8. * Supported device:                                  *
  9. * DJGPP devices.                                  *
  10. *******************************************************************************
  11. * History:                                      *
  12. *  17 Feb 92 - Version 1.0 by Gershon Elber - support for DJGPP.          *
  13. ******************************************************************************/
  14.  
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include <fcntl.h>
  19. #include <ctype.h>
  20. #include <graphics.h>
  21.  
  22. #ifdef DJGCC
  23. #include <pc.h>
  24. #endif /* DJGCC */
  25.  
  26. #include "intr_loc.h"
  27. #include "intr_gr.h"
  28.  
  29. #define    POINT_SIZE      0.05              /* Size of + marker drawn. */
  30. #define    POINT_TITLE     0.02   /* Distance between point title and + marker. */
  31.  
  32. #define HISTORY_SIZE    10    /* History buffer length for GRGetGraphicLine. */
  33. #define GR_LINE_LEN    80      /* Maximum chars read by GRGetGraphicLine. */
  34.  
  35. #define    CURSOR_IMAGE_X  24
  36. #define    CURSOR_IMAGE_Y  24
  37.  
  38. #define CURSOR_TYPE_STACK_SIZE 20     /* Size of stack to save cursor types. */
  39. #define VIEW_PORT_STACK_SIZE 20        /* Depth of view port setting stack. */
  40. #define TEXT_SETTING_STACK_SIZE 10         /* Depth of text setting stack. */
  41.  
  42. #define MAP_UP_X(x)  ((((x) - GRPanFactorX) << GRZoomFactor) + GRWidth2)
  43. #define MAP_UP_Y(y)  ((((y) - GRPanFactorY) << GRZoomFactor) + GRHeight2)
  44. #define MAP_DN_X(x)  ((((x) - GRPanFactorX) >> GRIZoomFactor) + GRWidth2)
  45. #define MAP_DN_Y(y)  ((((y) - GRPanFactorY) >> GRIZoomFactor) + GRHeight2)
  46. #define INVMAP_UP_X(x)  ((((x) - GRWidth2) >> GRZoomFactor) + GRPanFactorX)
  47. #define INVMAP_UP_Y(y)  ((((y) - GRHeight2) >> GRZoomFactor) + GRPanFactorY)
  48. #define INVMAP_DN_X(x)  ((((x) - GRWidth2) << GRIZoomFactor) + GRPanFactorX)
  49. #define INVMAP_DN_Y(y)  ((((y) - GRHeight2) << GRIZoomFactor) + GRPanFactorY)
  50.  
  51. typedef struct TextJustifyStruct {
  52.     GRTextHorizJustifyType HorizJustify;
  53.     GRTextVertJustifyType VertJustify;
  54. } TextJustifyStruct;
  55.  
  56. typedef struct ImageSaveStruct {
  57.     int Width, Height;
  58.     char *Data;
  59. } ImageSaveStruct;
  60.  
  61. int GRScreenMaxX, GRScreenMaxY;     /* The maximum resolution of the screen. */
  62. int GRScreenMaxColors;              /* The maximum # of colors available. */
  63. IntrRType GRScreenAspect = 1.0; /* Screen aspect ratio (pixel width/height). */
  64. int GRCurrentCursorX, GRCurrentCursorY;          /* Cursor current position. */
  65. int GRFontName, GRFontSize;         /* Global information on font used. */
  66. int GRDrawText;            /* If can not zoom down text, force draw. */
  67. int GRGraphMode = 0, GRGraphDriver = 0;       /* What driver/mode are we in. */
  68.  
  69. static int GRScreenMaxX2, GRScreenMaxY2;      /* Half of maximum resolution. */
  70. static VoidPtr GRPutImage = NULL;     /* If not null, used to save getimage. */
  71. static int GRScreenGraphicMode;
  72. static int GRTextSize = 1;    /* Current text size: 1 = 8x8, 2 = 16x16 etc.. */
  73. static int GRWidth2 = 100;
  74. static int GRHeight2 = 100;
  75. static int GRMinX = 0;
  76. static int GRMinY = 0;
  77. static int GRZoomFactor = 0;
  78. static int GRIZoomFactor = 0;
  79. static int GRPanFactorX = 0;
  80. static int GRPanFactorY = 0;
  81. static int ViewPortStackPtr = 0;
  82. static int GRCrntColor = WHITE;               /* Current drawing color. */
  83. static int GRDrawMode = 0x00;           /* 0x00 for COPY, 0x100 for XOR mode. */
  84. static int GRLastMoveToX , GRLastMoveToY;
  85. static int CrntHorizCenter = GR_TEXT_HJUSTIFY_CENTER;
  86. static int CrntVertCenter = GR_TEXT_VJUSTIFY_CENTER;
  87.  
  88. static struct ImageSaveStruct *CursorImageBuffer  = NULL;
  89.  
  90. static struct GrRegion *ViewPortStack[VIEW_PORT_STACK_SIZE];
  91. static int TextSettingStackPtr = 0;
  92. static struct TextJustifyStruct TextSettingStack[TEXT_SETTING_STACK_SIZE];
  93. IntrInt2PtrFunc GlblGetChFunc = IntrGetEventWait;
  94.  
  95. static char HistoryBuffer[HISTORY_SIZE][GR_LINE_LEN + 1];
  96. static int HistoryBufLen = 0;
  97.  
  98. static struct GrRegion *ScrnRegion, *CrntRegion;
  99.  
  100. static void GRComputeTextOffset(char *s, int *x, int *y);
  101. static void MoveOverlapMem(char *Dest, char *Src, int Len);
  102. static int GRGetKey(void);
  103.  
  104. /****************************************************************************
  105. * Routine to reset all the system to starting condition    :            *
  106. ****************************************************************************/
  107. void GRInitGraph()
  108. {
  109.     int    i, j, GRScreenErrorCode;
  110.  
  111.     if (GRScreenGraphicMode) return;
  112.  
  113.     ViewPortStackPtr = 0;          /* Make sure view port stack is empty. */
  114.  
  115.     GrSetMode(GR_default_graphics);
  116.  
  117.     ScrnRegion = GrScreenRegion();
  118.  
  119.     GRScreenMaxX = ScrnRegion->width;
  120.     GRScreenMaxY = ScrnRegion->height;
  121.     GRScreenMaxX2 = GRScreenMaxX / 2;
  122.     GRScreenMaxY2 = GRScreenMaxY / 2;
  123.  
  124.     GRCurrentCursorX = GRScreenMaxX2;
  125.     GRCurrentCursorY = GRScreenMaxY2;
  126.  
  127.     GRScreenMaxColors = 256;
  128.  
  129.     ScrnRegion->Box(0, 0, GRScreenMaxX, GRScreenMaxY, BLACK);
  130.     CrntRegion = ScrnRegion;
  131.  
  132.     /* Prepare the cursor (Arrow) image : */
  133.     GRSetColor(GRScreenMaxColors - 1);
  134.     GRSLine(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y);
  135.     j = CURSOR_IMAGE_X / 3;
  136.     for    (i = 1; i <= 7; i++) GRSLine(0, 0, j, j + i);/* Draw the arrow head. */
  137.     j = CURSOR_IMAGE_Y / 3;
  138.     for    (i = 1; i <= 7; i++) GRSLine(0, 0, j + i, j);
  139.  
  140.     CursorImageBuffer = (struct ImageSaveStruct *)
  141.     GRGetImageBuffer(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y);
  142.  
  143.     GRClearAllScreen();
  144.  
  145.     GRScreenGraphicMode = TRUE;
  146. }
  147.  
  148. /****************************************************************************
  149. * Routine to close and shutdown    graphic    mode :                    *
  150. ****************************************************************************/
  151. void GRCloseGraph(void)
  152. {
  153.     if (!GRScreenGraphicMode) return;
  154.  
  155.     GrSetMode(GR_default_text);
  156. }
  157.  
  158. /****************************************************************************
  159. * Routine to set line style parameters.                        *
  160. ****************************************************************************/
  161. void GRSetLineStyle(int LineStyle, unsigned int Pattern, int Thickness)
  162. {
  163. }
  164.  
  165. /****************************************************************************
  166. * Routine to set fill style parameters.                        *
  167. ****************************************************************************/
  168. void GRSetFillStyle(int Pattern, int Color)
  169. {
  170.     GRCrntColor = Color;
  171. }
  172.  
  173. /****************************************************************************
  174. * Routine to set write mode parameters - non zero XOR mode, zero COPY mode. *
  175. ****************************************************************************/
  176. void GRSetWriteMode(int DrawMode)
  177. {
  178.     GRDrawMode = DrawMode ? 0x100 : 0x00;
  179. }
  180.  
  181. /****************************************************************************
  182. * Routine to set text horizontal and vertical justification.            *
  183. ****************************************************************************/
  184. void GRSetTextJustify(int HorizCenter, int VertCenter)
  185. {
  186.     CrntHorizCenter = HorizCenter;
  187.     CrntVertCenter = VertCenter;
  188. }
  189.  
  190. /****************************************************************************
  191. * Routine to set zoom factor for drawing.                    *
  192. *   Zoom factor of 0 means regular drawing while each inc/decremenet zooms  *
  193. * up/down respectively by a factor of 2.                    *
  194. ****************************************************************************/
  195. void GRSetZoomFactor(int ZoomFactor)
  196. {
  197.     GRZoomFactor = ZoomFactor;
  198.     GRIZoomFactor = -GRZoomFactor;
  199. }
  200.  
  201. /****************************************************************************
  202. * Routine to set pan factors for drawing space.                    *
  203. ****************************************************************************/
  204. void GRSetPanFactors(int PanFactorX, int PanFactorY)
  205. {
  206.     GRPanFactorX = PanFactorX;
  207.     GRPanFactorY = PanFactorY;
  208. }
  209.  
  210. /****************************************************************************
  211. * Routine to set text drawing parameters, in drawing space.            *
  212. ****************************************************************************/
  213. void GRSetTextStyle(int GRFontName, int Direction, int Size)
  214. {
  215.     GRTextSize = Size + GRZoomFactor;
  216. }
  217.  
  218. /****************************************************************************
  219. * Routine to set text drawing parameters, in screen space.            *
  220. ****************************************************************************/
  221. void GRSetSTextStyle(int GRFontName, int Direction, int Size)
  222. {
  223. }
  224.  
  225. /****************************************************************************
  226. * Routine to get an image rectangle into real memory.                *
  227. ****************************************************************************/
  228. void *GRGetImageBuffer(int x1, int y1, int x2, int y2)
  229. {
  230.     int i, Width;
  231.     struct ImageSaveStruct
  232.     *Buffer = new struct ImageSaveStruct;
  233.     char *p,
  234.     *Visual = (char *) (0xd0000000 +
  235.                 (CrntRegion -> abs_y + y1) * GRScreenMaxX +
  236.                 (CrntRegion -> abs_x + x1));
  237.  
  238.     Width = Buffer -> Width = x2 - x1 + 1;
  239.     Buffer -> Height = y2 - y1 + 1;
  240.     Buffer -> Data = p = new char[Buffer -> Width * Buffer -> Height];
  241.  
  242.     for (i = Buffer -> Height; i > 0; i--) {
  243.     memcpy(p, Visual, Width);
  244.     p += Width;
  245.     Visual += GRScreenMaxX;
  246.     }
  247.  
  248.     return (void *) Buffer;
  249. }
  250.  
  251. /****************************************************************************
  252. * Routine to put an image rectangle from real memory into the display.        *
  253. ****************************************************************************/
  254. void GRPutImageBuffer(int x1, int y1, void *Buffer)
  255. {
  256.     struct ImageSaveStruct
  257.     *IBuffer = (ImageSaveStruct *) Buffer;
  258.     int i,
  259.     Width = IBuffer -> Width;
  260.     char
  261.     *p = IBuffer -> Data,
  262.     *Visual = (char *) (0xd0000000 +
  263.                 (CrntRegion -> abs_y + y1) * GRScreenMaxX +
  264.                 (CrntRegion -> abs_x + x1));
  265.  
  266.     for (i = IBuffer -> Height; i > 0; i--) {
  267.     memcpy(Visual, p, Width);
  268.     p += Width;
  269.     Visual += GRScreenMaxX;
  270.     }
  271.  
  272.     delete IBuffer -> Data;
  273.     delete IBuffer;
  274. }
  275.  
  276. /****************************************************************************
  277. * Routine to draw the cursor as an arrow.                    *
  278. ****************************************************************************/
  279. void GRPutArrowCursor(int x, int y)
  280. {
  281.     int i, j,
  282.     CursorWidth = CursorImageBuffer -> Width,
  283.     Width = MIN(CursorWidth, GRScreenMaxX - x);
  284.     char *cp, *vp,
  285.     *CursorData = CursorImageBuffer -> Data,
  286.     *VisualData = (char *) (0xd0000000 + y * GRScreenMaxX + x);
  287.  
  288.     for (i = CursorImageBuffer -> Height; i > 0; i--) {
  289.     cp = CursorData;
  290.     vp = VisualData;
  291.     for (j = 0; j < Width; j++) *vp++ ^= *cp++;
  292.  
  293.     CursorData += CursorWidth;
  294.     VisualData += GRScreenMaxX;
  295.     }
  296. }
  297.  
  298. /****************************************************************************
  299. * Routine to XOR a rectangle area on screen using current color.        *
  300. ****************************************************************************/
  301. void GRXORRectangle(int x1, int y1, int x2, int y2)
  302. {
  303.     ScrnRegion->Box(x1, y1, x2 - x1 + 1, y2 - y1 + 1, GRCrntColor | 0x100);
  304. }
  305.  
  306. /****************************************************************************
  307. * External reference for the mappings.                        *
  308. ****************************************************************************/
  309. int GRMapX(int x)
  310. {
  311.     return (GRZoomFactor > 0 ? MAP_UP_X(x) : MAP_DN_X(x)) + GRMinX;
  312. }
  313.  
  314. int GRMapY(int y)
  315. {
  316.     return (GRZoomFactor > 0 ? MAP_UP_Y(y) : MAP_DN_Y(y)) + GRMinY;
  317. }
  318.  
  319. /****************************************************************************
  320. * External reference for the inverse mapping.                        *
  321. ****************************************************************************/
  322. int GRInvMapX(int x)
  323. {
  324.     x -= GRMinX;
  325.     return (GRZoomFactor > 0 ? INVMAP_UP_X(x) : INVMAP_DN_X(x));
  326. }
  327.  
  328. int GRInvMapY(int y)
  329. {
  330.     y -= GRMinY;
  331.     return (GRZoomFactor > 0 ? INVMAP_UP_Y(y) : INVMAP_DN_Y(y));
  332. }
  333.  
  334. /****************************************************************************
  335. * Routine to draw a line, in Object spaces.                        *
  336. ****************************************************************************/
  337. void GRLine(int x1, int y1, int x2, int y2)
  338. {
  339.     if (GRZoomFactor > 0) {
  340.         CrntRegion->Line(MAP_UP_X(x1),
  341.              MAP_UP_Y(y1),
  342.              GRLastMoveToX = MAP_UP_X(x2),
  343.              GRLastMoveToY = MAP_UP_Y(y2),
  344.              GRCrntColor);
  345.     }
  346.     else {
  347.     CrntRegion->Line(MAP_DN_X(x1),
  348.              MAP_DN_Y(y1),
  349.              GRLastMoveToX = MAP_DN_X(x2),
  350.              GRLastMoveToY = MAP_DN_Y(y2),
  351.              GRCrntColor);
  352.     }
  353. }
  354.  
  355. /****************************************************************************
  356. * Routine to move to a new position, in Object space.                *
  357. ****************************************************************************/
  358. void GRMoveTo(int x, int y)
  359. {
  360.     if (GRZoomFactor > 0) {
  361.         GRLastMoveToX = MAP_UP_X(x);
  362.     GRLastMoveToY = MAP_UP_Y(y);
  363.     }
  364.     else {
  365.         GRLastMoveToX = MAP_DN_X(x);
  366.     GRLastMoveToY = MAP_DN_Y(y);
  367.     }
  368. }
  369.  
  370. /****************************************************************************
  371. * Routine to draw to a new position, in Object space.                *
  372. ****************************************************************************/
  373. void GRLineTo(int x, int y)
  374. {
  375.     int GRLineToX, GRLineToY;
  376.  
  377.     if (GRZoomFactor > 0) {
  378.         GRLineToX = MAP_UP_X(x);
  379.     GRLineToY = MAP_UP_Y(y);
  380.     }
  381.     else {
  382.         GRLineToX = MAP_DN_X(x);
  383.     GRLineToY = MAP_DN_Y(y);
  384.     }
  385.  
  386.     CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY,
  387.                         GRCrntColor | GRDrawMode);
  388.     GRLastMoveToX = GRLineToX;
  389.     GRLastMoveToY = GRLineToY;
  390. }
  391.  
  392. /****************************************************************************
  393. * Routine to move to a new position, in Screen (pixels) space.            *
  394. ****************************************************************************/
  395. void GRSMoveTo(int x, int y)
  396. {
  397.     GRLastMoveToX = x;
  398.     GRLastMoveToY = y;
  399. }
  400.  
  401. /****************************************************************************
  402. * Routine to draw to a new position, in Screen (pixels) space.            *
  403. ****************************************************************************/
  404. void GRSLineTo(int x, int y)
  405. {
  406.     CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, x, y,
  407.              GRCrntColor | GRDrawMode);
  408.     GRLastMoveToX = x;
  409.     GRLastMoveToY = y;
  410. }
  411.  
  412. /****************************************************************************
  413. * Routine to draw to a new position, in Screen (pixels) space.            *
  414. ****************************************************************************/
  415. void GRSLine(int x1, int y1, int x2, int y2)
  416. {
  417.     CrntRegion->Line(x1, y1, x2, y2, GRCrntColor | GRDrawMode);
  418.     GRLastMoveToX = x2;
  419.     GRLastMoveToY = y2;
  420. }
  421.  
  422. /****************************************************************************
  423. * Routine to move to a new position relative to current one, as in Object   *
  424. * space.                                    *
  425. ****************************************************************************/
  426. void GRMoveRel(int x, int y)
  427. {
  428.     if (GRZoomFactor > 0) {
  429.     GRLastMoveToX += x << GRZoomFactor;
  430.     GRLastMoveToY += y << GRZoomFactor;
  431.     }
  432.     else {
  433.     GRLastMoveToX += x >> GRIZoomFactor;
  434.     GRLastMoveToY += y >> GRIZoomFactor;
  435.     }
  436. }
  437.  
  438. /****************************************************************************
  439. * Routine to line to a new position relative to current one, as in Object   *
  440. * space.                                    *
  441. ****************************************************************************/
  442. void GRLineRel(int x, int y)
  443. {
  444.     int GRLineToX = GRLastMoveToX,
  445.     GRLineToY = GRLastMoveToY;
  446.  
  447.     if (GRZoomFactor > 0) {
  448.         GRLineToX += x << GRZoomFactor;
  449.     GRLineToY += y << GRZoomFactor;
  450.     }
  451.     else {
  452.         GRLineToX += x >> GRIZoomFactor;
  453.     GRLineToY += y >> GRIZoomFactor;
  454.     }
  455.  
  456.     CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY,
  457.                         GRCrntColor | GRDrawMode);
  458.     GRLastMoveToX = GRLineToX;
  459.     GRLastMoveToY = GRLineToY;
  460. }
  461.  
  462. /****************************************************************************
  463. * Routine to move to a new position relative to current one, as in Screen   *
  464. * space (pixel coords.).                            *
  465. ****************************************************************************/
  466. void GRSMoveRel(int x, int y)
  467. {
  468.     GRLastMoveToX += x;
  469.     GRLastMoveToY += y;
  470. }
  471.  
  472. /****************************************************************************
  473. * Routine to line to a new position relative to current one, as in Screen   *
  474. * space (pixel coords.).                            *
  475. ****************************************************************************/
  476. void GRSLineRel(int x, int y)
  477. {
  478.     int GRLineToX = GRLastMoveToX + x,
  479.     GRLineToY = GRLastMoveToY + y;
  480.  
  481.     CrntRegion->Line(GRLastMoveToX, GRLastMoveToY, GRLineToX, GRLineToY,
  482.                         GRCrntColor | GRDrawMode);
  483.     GRLastMoveToX = GRLineToX;
  484.     GRLastMoveToY = GRLineToY;
  485. }
  486.  
  487. /****************************************************************************
  488. * Routine to draw a new polyline and fill it if Fill, in screen space.        *
  489. ****************************************************************************/
  490. void GRPoly(int n, int *Points, int Fill)
  491. {
  492.     int i, ii;
  493.  
  494.     if (GRZoomFactor > 0)
  495.         for (i = 0; i < n; i++) {
  496.         ii = i << 1;
  497.             Points[ii] = MAP_UP_X(Points[ii]);
  498.             Points[ii + 1] = MAP_UP_Y(Points[ii + 1]);
  499.      }
  500.     else
  501.         for (i = 0; i < n; i++) {
  502.         ii = i << 1;
  503.             Points[ii] = MAP_DN_X(Points[ii]);
  504.             Points[ii + 1] = MAP_DN_Y(Points[ii + 1]);
  505.      }
  506.  
  507.     if (Fill) {
  508.     /* There is a problem with BLACK color that fillpoly sometime does   */
  509.     /* not clear the border properly, so we need to redo it by drawpoly. */
  510.     IntrFatalError("Fill not supported in this driver.\n");
  511.     }
  512.     else {
  513.     GRSMoveTo(Points[n * 2 - 2], Points[n * 2 - 1]);
  514.     for (i = 0; i < n; i++) {
  515.         ii = i << 1;
  516.         GRSLineTo(Points[ii], Points[ii + 1]);
  517.     }
  518.     }
  519. }
  520.  
  521. /****************************************************************************
  522. * Routine to draw a bar, in drawing space.                    *
  523. ****************************************************************************/
  524. void GRBar(int x1, int y1, int x2, int y2)
  525. {
  526.     if (GRZoomFactor > 0) {
  527.     x1 = MAP_UP_X(x1);
  528.     y1 = MAP_UP_Y(y1);
  529.     x2 = MAP_UP_X(x2);
  530.     y2 = MAP_UP_Y(y2);
  531.     }
  532.     else {
  533.     x1 = MAP_DN_X(x1);
  534.     y1 = MAP_DN_Y(y1);
  535.     x2 = MAP_DN_X(x2);
  536.     y2 = MAP_DN_Y(y2);
  537.     }
  538.  
  539.     CrntRegion->Box(x1, y1, x2 - x1 + 1, y2 - y1 + 1, GRCrntColor | GRDrawMode);
  540. }
  541.  
  542. /****************************************************************************
  543. * Routine to draw a bar, in screen space.                    *
  544. ****************************************************************************/
  545. void GRSBar(int x1, int y1, int x2, int y2)
  546. {
  547.     CrntRegion->Box(x1, y1, x2 - x1 + 1, y2 - y1 + 1, GRCrntColor | GRDrawMode);
  548. }
  549.  
  550. /****************************************************************************
  551. * Routine to draw a circle, in drawing space.                    *
  552. ****************************************************************************/
  553. void GRCircle(int x, int y, int r)
  554. {
  555.     IntrFatalError("Fill not supported in this driver.\n");
  556. }
  557.  
  558. /****************************************************************************
  559. * Routine to draw an arc, in drawing space.                    *
  560. * As the Y axes is inverted the Angles should be inverted as well.        *
  561. ****************************************************************************/
  562. void GRArc(int x, int y, int StAngle, int EndAngle, int r)
  563. {
  564.     IntrFatalError("Fill not supported in this driver.\n");
  565. }
  566.  
  567. /****************************************************************************
  568. * Routine to draw the given text in given drawing space coordinates.        *
  569. ****************************************************************************/
  570. IntrBType GRDrawingText(void)
  571. {
  572.     return GRTextSize > 0 || GRDrawText;
  573. }
  574.  
  575. /****************************************************************************
  576. * Routine to compute text justification offset according to given string.   *
  577. ****************************************************************************/
  578. static void GRComputeTextOffset(char *s, int *x, int *y)
  579. {
  580.     int Width = GRGetTextWidth(s),
  581.         Height = GRGetTextHeight(s);
  582.  
  583.     switch (CrntHorizCenter) {
  584.         case GR_TEXT_HJUSTIFY_LEFT:
  585.             *x = 0;
  586.             break;
  587.     case GR_TEXT_HJUSTIFY_CENTER:
  588.         *x = -Width/ 2;
  589.         break;
  590.     case GR_TEXT_HJUSTIFY_RIGHT:
  591.         *x = -Width;
  592.         break;
  593.     }
  594.  
  595.     switch (CrntVertCenter) {
  596.     case GR_TEXT_VJUSTIFY_BOTTOM:
  597.         *y = -Height;
  598.         break;
  599.     case GR_TEXT_VJUSTIFY_CENTER:
  600.         *y = -Height / 2;
  601.         break;
  602.     case GR_TEXT_VJUSTIFY_TOP:
  603.         *y = 0;
  604.         break;
  605.     }
  606. }
  607.  
  608. /****************************************************************************
  609. * Routine to draw the given text in given drawing space coordinates.        *
  610. ****************************************************************************/
  611. void GRText(int x, int y, char *s)
  612. {
  613.     int XOffset, YOffset;
  614.  
  615.     GRComputeTextOffset(s, &XOffset, &YOffset);
  616.  
  617.     /* If text can not be zoom down and we are not forced to draw - dont. */
  618.     if (GRTextSize < 1 && !GRDrawText) return;
  619.  
  620.     if (GRZoomFactor > 0)
  621.         CrntRegion->Text(MAP_UP_X(x) + XOffset, MAP_UP_Y(y) + YOffset,
  622.              s, GRCrntColor, -1);
  623.     else
  624.         CrntRegion->Text(MAP_DN_X(x) + XOffset, MAP_DN_Y(y) + YOffset,
  625.              s, GRCrntColor, -1);
  626. }
  627.  
  628. /****************************************************************************
  629. * Routine to draw the given text in given screen space coordinates.        *
  630. ****************************************************************************/
  631. void GRSText(int x, int y, char *s)
  632. {
  633.     int XOffset, YOffset;
  634.  
  635.     GRComputeTextOffset(s, &XOffset, &YOffset);
  636.  
  637.     CrntRegion->Text(x + XOffset, y + YOffset, s, GRCrntColor, -1);
  638. }
  639.  
  640. /****************************************************************************
  641. * Routine to draw the given text in given screen space coordinates.        *
  642. * A Black shadow is drawn for the given string.                    *
  643. ****************************************************************************/
  644. void GRSTextShadow(int x, int y, int Color, char *s)
  645. {
  646.     int XOffset, YOffset;
  647.  
  648.     GRComputeTextOffset(s, &XOffset, &YOffset);
  649.  
  650.     CrntRegion->Text(x + 2 + XOffset, y + 2 + YOffset, s, BLACK, -1);
  651.     CrntRegion->Text(x + XOffset, y + YOffset, s, Color, -1);
  652. }
  653.  
  654. /****************************************************************************
  655. * Routine to get string width in pixel.                        *
  656. ****************************************************************************/
  657. int GRGetTextWidth(char *Str)
  658. {
  659.     return 8 * strlen(Str);
  660. }
  661.  
  662. /****************************************************************************
  663. * Routine to get string height in pixel.                    *
  664. ****************************************************************************/
  665. int GRGetTextHeight(char *Str)
  666. {
  667.     return 16;
  668. }
  669.  
  670. /****************************************************************************
  671. * Routine to push current font type and text attributes.            *
  672. ****************************************************************************/
  673. void GRPushTextSetting(void)
  674. {
  675.     if (TextSettingStackPtr >= TEXT_SETTING_STACK_SIZE)
  676.     IntrFatalError("Text setting stack overflow.");
  677.  
  678.     TextSettingStack[TextSettingStackPtr].HorizJustify = CrntHorizCenter;
  679.     TextSettingStack[TextSettingStackPtr++].VertJustify = CrntVertCenter;
  680. }
  681.  
  682. /****************************************************************************
  683. * Routine to pop current font type and text attributes.                *
  684. ****************************************************************************/
  685. void GRPopTextSetting(void)
  686. {
  687.     if (--TextSettingStackPtr < 0)
  688.     IntrFatalError("Text setting stack underflow.");
  689.  
  690.     CrntHorizCenter = TextSettingStack[TextSettingStackPtr].HorizJustify;
  691.     CrntVertCenter = TextSettingStack[TextSettingStackPtr].VertJustify;
  692. }
  693.  
  694. /****************************************************************************
  695. * Routine to set color to color within range.                    *
  696. ****************************************************************************/
  697. void GRSetColor(int Color)
  698. {
  699.     if (Color >= GRScreenMaxColors)
  700.     Color = Color % (GRScreenMaxColors - 1) + 1;
  701.     GRCrntColor = Color;
  702. }
  703.  
  704. /****************************************************************************
  705. * Routine to get current active color.                        *
  706. ****************************************************************************/
  707. int GRGetColor(void)
  708. {
  709.     return GRCrntColor;
  710. }
  711.  
  712. /****************************************************************************
  713. * Routine to set one color index RGB values.                    *
  714. ****************************************************************************/
  715. void GRSetRGBPalette(int Index, int Red, int Green, int Blue)
  716. {
  717.     GrSetColor(Index, Red, Green, Blue);
  718. }
  719.  
  720. /*****************************************************************************
  721. *   Routine to clear all the screen.                         *
  722. *****************************************************************************/
  723. void GRClearAllScreen(void)
  724. {
  725.     ScrnRegion->Box(0, 0, GRScreenMaxX, GRScreenMaxY, BLACK);
  726. }
  727.  
  728. /*****************************************************************************
  729. *   Routine to clear given rectangle viewport.                     *
  730. *****************************************************************************/
  731. void GRClearViewPort(int x1, int y1, int x2, int y2)
  732. {
  733.     ScrnRegion->Box(x1, y1, x2, y2, BLACK);
  734. }
  735.  
  736. /*****************************************************************************
  737. *   Routine to set given rectangle viewport.                     *
  738. *****************************************************************************/
  739. void _GRSetViewPort(int x1, int y1, int x2, int y2)
  740. {
  741.     _GRSetViewPort2(x1, y1, x2, y2, TRUE);
  742. }
  743.  
  744. /*****************************************************************************
  745. *   Routine to set given rectangle viewport.                     *
  746. *****************************************************************************/
  747. void _GRSetViewPort2(int x1, int y1, int x2, int y2, IntrBType Clip)
  748. {
  749.     if (CrntRegion != ScrnRegion)
  750.     delete CrntRegion;
  751.     CrntRegion = ScrnRegion->SubRegion(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
  752. }
  753.  
  754. /*****************************************************************************
  755. *   Routine to set given rectangle viewport.                     *
  756. *****************************************************************************/
  757. void GRGetViewPort(int *x1, int *y1, int *x2, int *y2)
  758. {
  759.     *x1 = CrntRegion -> abs_x;
  760.     *y1 = CrntRegion -> abs_y;
  761.     *x2 = CrntRegion -> width + CrntRegion -> abs_x - 1;
  762.     *y2 = CrntRegion -> height + CrntRegion -> abs_y - 1;
  763. }
  764.  
  765. /*****************************************************************************
  766. *   Routine to set given rectangle viewport.                     *
  767. *****************************************************************************/
  768. void GRSetViewPort(int x1, int y1, int x2, int y2)
  769. {
  770.     _GRSetViewPort2(x1, y1, x2, y2, TRUE);
  771.     GRWidth2 = (x2 - x1) / 2;
  772.     GRHeight2 = (y2 - y1) / 2;
  773.     GRMinX = x1;
  774.     GRMinY = y1;
  775. }
  776.  
  777. /*****************************************************************************
  778. *   Routine to push current view port.                         *
  779. *****************************************************************************/
  780. void GRPushViewPort(void)
  781. {
  782.     if (ViewPortStackPtr >= VIEW_PORT_STACK_SIZE)
  783.     IntrFatalError("View port stack overflow.");
  784.  
  785.     ViewPortStack[ViewPortStackPtr++] = CrntRegion;
  786.     CrntRegion = ScrnRegion;
  787. }
  788.  
  789. /*****************************************************************************
  790. *   Routine to pop current view port.                         *
  791. *****************************************************************************/
  792. void GRPopViewPort(void)
  793. {
  794.     if (--ViewPortStackPtr < 0)
  795.     IntrFatalError("View port stack underflow.");
  796.  
  797.     CrntRegion = ViewPortStack[ViewPortStackPtr];
  798.     GRWidth2 = CrntRegion->width / 2;
  799.     GRHeight2 = CrntRegion->height / 2;
  800.     GRMinX = CrntRegion->abs_x;
  801.     GRMinY = CrntRegion->abs_y;
  802. }
  803.  
  804. /*****************************************************************************
  805. * Routine to read one line terminated by <Enter> and visualized    on graphic   *
  806. * screen.                                     *
  807. * Full line editing is supported which includes:                 *
  808. * 1. Right and left arrows to move along the line.                 *
  809. * 2. Up and down arrows to cirlce along a history buffer.             *
  810. * 3. Delete to delete current character.                     *
  811. * 4. Insert to toggle Insert/Overwrite mode.                     *
  812. * 5. Backspace to delete character before current one.                 *
  813. * 6. Home/End to move to beginning/End of string respectively.             *
  814. * 7. Return to accept current line.                         *
  815. * 8. Esc to clear current line.                             *
  816. * If s is not empty it is used as starting string.                 *
  817. * Line is drawn    starting from position x, y on screen (normalized -1..1).    *
  818. *****************************************************************************/
  819. void GRGetGraphicLine(int WindowID, int x, int y, char s[], int SLen,
  820.               int WindowLen, int ForeColor, int BackColor)
  821. {
  822.     static int
  823.     Insert = TRUE;
  824.     int    NextKey, FirstVisible, i,
  825.     Xstep = 8,                 /* Basically the font size. */
  826.     Len = strlen(s),
  827.     CursorPos = Len,
  828.         FirstTime = TRUE,
  829.     EndOfString = FALSE,
  830.     HistoryBufCrnt = -1;
  831.     char DisplayLine[GR_LINE_LEN], *Cursor;
  832.     _IntrWindowStruct
  833.     *Window = WindowID ? _IntrFindWndwUsingID(WindowID) : NULL;
  834.     IntrBBoxStruct
  835.     *BBox = Window ? &Window -> BBox : NULL;
  836.     struct GrRegion
  837.     *WRegion = BBox ? ScrnRegion->SubRegion(BBox -> Xmin,
  838.                         BBox -> Ymin,
  839.                         BBox -> Xmax - BBox -> Xmin + 1,
  840.                         BBox -> Ymax - BBox -> Ymin + 1)
  841.             : ScrnRegion;
  842.  
  843.     GRPushTextSetting();
  844.     GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP);
  845.  
  846.     while (!EndOfString) {
  847.     /* Can not display the whole string, so set first visible char:  */
  848.     FirstVisible = CursorPos > WindowLen - 2 ? CursorPos - WindowLen + 2
  849.                          : 0;
  850.  
  851.     /* Prepare the part of s to be displayed: */
  852.     strncpy(DisplayLine, &s[FirstVisible], GR_LINE_LEN - 1);
  853.     DisplayLine[MIN(WindowLen, GR_LINE_LEN - 1)] = 0;
  854.  
  855.     Cursor = (Insert ? "_" : "-");
  856.  
  857.     WRegion->Text(x, y, DisplayLine, ForeColor, BackColor);
  858.     WRegion->Text(x + (CursorPos - FirstVisible) * Xstep, y, Cursor,
  859.                                 WHITE, -1);
  860.  
  861.     if ((NextKey = GRGetKey()) != KEY_REFRESH || FirstTime) {
  862.         WRegion->Text(x, y, DisplayLine, BackColor, BackColor);
  863.         WRegion->Text(x + (CursorPos - FirstVisible) * Xstep, y, Cursor,
  864.                                 BackColor, -1);
  865.     }
  866.     FirstTime = FALSE;
  867.  
  868.     switch (NextKey) {
  869.         case KEY_BSPACE:
  870.         if (CursorPos == 0) {
  871.             GRTone(1000, 100);             /* Do some noise... */
  872.             break;
  873.         }
  874.         MoveOverlapMem(&s[CursorPos - 1], &s[CursorPos],
  875.                               Len - CursorPos + 1);
  876.         CursorPos--;
  877.         Len--;
  878.         break;
  879.         case KEY_DELETE:
  880.         if (CursorPos >= Len) {
  881.             GRTone(1000, 100);             /* Do some noise... */
  882.             break;
  883.         }
  884.         MoveOverlapMem(&s[CursorPos], &s[CursorPos + 1],
  885.                                   Len - CursorPos);
  886.         Len--;
  887.         break;
  888.         case KEY_RIGHT:
  889.         if (CursorPos >= Len) {
  890.             GRTone(1000, 100);             /* Do some noise... */
  891.             break;
  892.         }
  893.         CursorPos++;
  894.         break;
  895.         case KEY_LEFT:
  896.         if (CursorPos <= 0) {
  897.             GRTone(1000, 100);             /* Do some noise... */
  898.             break;
  899.         }
  900.         CursorPos--;
  901.         break;
  902.         case KEY_UP:
  903.             if (HistoryBufLen == 0) {
  904.             GRTone(1000, 100);             /* Do some noise... */
  905.             break;
  906.             }
  907.  
  908.             if (++HistoryBufCrnt >= HistoryBufLen) HistoryBufCrnt = 0;
  909.  
  910.         strcpy(s, HistoryBuffer[HistoryBufCrnt]);
  911.         CursorPos = Len = strlen(s);
  912.         break;
  913.         case KEY_DOWN:
  914.             if (HistoryBufLen == 0) {
  915.             GRTone(1000, 100);             /* Do some noise... */
  916.             break;
  917.             }
  918.  
  919.             if (--HistoryBufCrnt < 0) HistoryBufCrnt = HistoryBufLen - 1;
  920.  
  921.         strcpy(s, HistoryBuffer[HistoryBufCrnt]);
  922.         CursorPos = Len = strlen(s);
  923.         break;
  924.         case KEY_RETURN:
  925.         EndOfString = TRUE;
  926.         break;
  927.         case KEY_ESC:
  928.         Len = 0;                /* Clear everything. */
  929.         CursorPos = 0;
  930.         s[0] = 0;
  931.         break;
  932.         case KEY_HOME:
  933.         CursorPos = 0;
  934.         break;
  935.         case KEY_END:
  936.         CursorPos = Len;
  937.         break;
  938.          case KEY_INSERT:
  939.         Insert = !Insert;
  940.         break;
  941.         case KEY_NONE:
  942.             GRTone(1000, 100);             /* Do some noise... */
  943.         GRTone(500, 200);
  944.         break;
  945.         case KEY_REFRESH:              /* Internal event to intr_lib. */
  946.         if (Window != NULL) {
  947.             _GRSetViewPort(Window -> BBox.Xmin, Window -> BBox.Ymin,
  948.                        Window -> BBox.Xmax, Window -> BBox.Ymax);
  949.             x = TEXT_BORDER,
  950.                  y = Window -> BBox.Ymax - Window -> BBox.Ymin -
  951.                        TEXT_BORDER - GRGetTextHeight("M");
  952.         }
  953.         GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP);
  954.         break;
  955.         default:                      /* Regular ascii char. */
  956.         if (Insert) {
  957.             MoveOverlapMem(&s[CursorPos + 1], &s[CursorPos],
  958.                             Len - CursorPos + 1);
  959.             Len++;
  960.         }
  961.         else if (CursorPos == Len)
  962.             Len++;            /* We are on last character. */
  963.         s[CursorPos++] = NextKey;
  964.         if (CursorPos == Len) s[CursorPos] = 0;
  965.         break;
  966.     }
  967.     if (SLen <= Len - 1) {    /* End of buffer - can not save more info. */
  968.         Len = SLen - 1;
  969.         if (CursorPos > Len) CursorPos = Len;
  970.         GRTone(1000, 100);                 /* Do some noise... */
  971.     }
  972.     }
  973.  
  974.     GRPopTextSetting();
  975.  
  976.     /* Update the history buffer: */
  977.     for (i = HISTORY_SIZE - 1; i > 0; i--)
  978.     strncpy(HistoryBuffer[i], HistoryBuffer[i - 1], GR_LINE_LEN);
  979.     strncpy(HistoryBuffer[0], s, GR_LINE_LEN);
  980.     HistoryBufLen = MIN(HISTORY_SIZE, HistoryBufLen + 1);
  981.  
  982.     if (WRegion != ScrnRegion) delete WRegion;
  983. }
  984.  
  985. /*****************************************************************************
  986. * Same as memcpy but allow Src and Dest to overlap.                 *
  987. *****************************************************************************/
  988. static void MoveOverlapMem(char *Dest, char *Src, int Len)
  989. {
  990.     char TempStr[GR_LINE_LEN];
  991.  
  992.     memcpy(TempStr, Src, Len);
  993.     memcpy(Dest, TempStr, Len);
  994. }
  995.  
  996. /*****************************************************************************
  997. * Sets the function invoked to get a kbd event in GRGetKey.             *
  998. * NULL will recover the internal default - IntrGetEventWait.             *
  999. *****************************************************************************/
  1000. void GRSetGetKeyFunc(IntrInt2PtrFunc GetChFunc)
  1001. {
  1002.     if (GetChFunc == NULL)
  1003.     GlblGetChFunc = IntrGetEventWait;
  1004.     else
  1005.         GlblGetChFunc = GetChFunc;
  1006. }
  1007.  
  1008. /*****************************************************************************
  1009. * Get a key from keyboard, and translating operational keys into special     *
  1010. * codes (>255).                                     *
  1011. *****************************************************************************/
  1012. static int GRGetKey(void)
  1013. {
  1014.     int x, y;
  1015.  
  1016.     /* Detach the keyboard from moving the mouse so keyboard can be used to  */
  1017.     /* edit the input line instead.                         */
  1018.     _IntrDetachKbdFromMouse = TRUE;
  1019.     while (GlblGetChFunc(&x, &y) != INTR_EVNT_KEY);
  1020.     _IntrDetachKbdFromMouse = FALSE;
  1021.  
  1022.     if (x >= 256) {
  1023.     switch (x - 256) {    /* Extended code - get the next extended char. */
  1024.         case 72:
  1025.         return KEY_UP;
  1026.         case 80:
  1027.         return KEY_DOWN;
  1028.         case 75:
  1029.         return KEY_LEFT;
  1030.         case 77:
  1031.         return KEY_RIGHT;
  1032.         case 71:
  1033.         return KEY_HOME;
  1034.         case 79:
  1035.         return KEY_END;
  1036.         case 83:
  1037.         return KEY_DELETE;
  1038.         case 82:
  1039.         return KEY_INSERT;
  1040.         case KEY_REFRESH - 256:
  1041.         return KEY_REFRESH;
  1042.     }
  1043.     }
  1044.     else {
  1045.         switch (x) {
  1046.         case 8:
  1047.             return KEY_BSPACE;
  1048.         case 10:
  1049.         case 13:
  1050.             return KEY_RETURN;
  1051.         case 27:
  1052.             return KEY_ESC;
  1053.         default:
  1054.             if (isprint(x)) return x;
  1055.     }
  1056.     }
  1057.  
  1058.     return KEY_NONE;
  1059. }
  1060.  
  1061. /*****************************************************************************
  1062. * Routine to delay the specified amount in millisec.                 *
  1063. *****************************************************************************/
  1064. extern "C" void delay(int time)
  1065. {
  1066.     int i,
  1067.     j = 0;
  1068.  
  1069.     for (i = 0; i < 50000; i++) j += i + 5;          /* basically wait. */
  1070. }
  1071.  
  1072. /*****************************************************************************
  1073. * Routine to make some sound with given Frequency, Time milliseconds:         *
  1074. *****************************************************************************/
  1075. void GRTone(int Frequency, int Duration)
  1076. {
  1077.     sound(Frequency);
  1078.  
  1079.     delay(Duration);
  1080.  
  1081.     sound(0);
  1082. }
  1083.